import feature, string

def squish(obj, length):
	if 'squish' in dir(obj):
		lengthset = getLengths(obj.squish())
		for l in lengthset.lengths:
			if -l[0] <= length: return l[1]
		return '...'
	else:
		if len(str(obj)) > length: return '...'
		return str(obj)

class LengthSet:
	def __init__(self, strings):
		self.lengths = [(-len(x), x) for x in strings]
		self.lengths.sort()
	def strings(self):
		return [x[1] for x in self.lengths]
	def __add__(self, other):
		newstrings = []
		for i in self.strings():
			for j in other.strings():
				newstrings.append(i+j)
		#print "Add: %s + %s = %s" % (self, other, LengthSet(newstrings))
		return LengthSet(newstrings)
	def __or__(self, other):
		#print "Or: %s | %s = %s" % (self, other,
		#LengthSet(self.strings() + other.strings()))
		return LengthSet(self.strings() + other.strings())
	def max(self):
		return self.lengths[-1][0]
	def min(self):
		return self.lengths[0][0]
	def __str__(self):
		return "<LengthSet: %s>" % self.lengths

class Squisher(object):
	pass

def getLengths(obj):
	if isinstance(obj, Squisher): return obj.lengths
	elif 'squish' in dir(obj): return getLengths(obj.squish())
	else: return LengthSet([str(obj)])

class Concat(Squisher):
	def __init__(self, *items):
		self.items = items
		self.lengths = LengthSet([''])
		for item in items:
			self.lengths = self.lengths + getLengths(item)
	
class Choose(Squisher):
	def __init__(self, *items):
		self.items = items
		assert len(items)
		self.lengths = LengthSet([])
		
		for item in items:
			self.lengths = self.lengths | getLengths(item)

class Join(Squisher):
	def __init__(self, items, joiner):
		self.lengths = LengthSet([])
		curr = LengthSet([''])
		#if not len(items): return
		for item in items[:-1]:
			curr = curr + getLengths(item) + getLengths(joiner)
		#	self.lengths = self.lengths | curr
		#self.lengths = self.lengths + getLengths('...')
		#self.lengths = self.lengths | (curr + getLengths(items[-1]))
		if len(items):
			self.lengths = curr + getLengths(items[-1])

